function gpmodelgenes2mfile(gp,ID,filename,useAlias)
%GPMODELGENES2MFILE Converts individual genes of a multigene symbolic regression model to a standalone M file.
%
%   GPMODELGENES2MFILE(GP,'best') converts the "best" model, as evaluated
%   on the training data, to a standalone function in GPGENESMODEL.M
%
%   GPMODELGENES2MFILE(GP,'best','FILENAME') converts the 'best' model, as
%   evaluated on the training data, to a standalone function in FILENAME.M.
%
%   GPMODELGENES2MFILE(GP,'valbest','FILENAME') converts the 'best' model,
%   as evaluated on the validation data, to a function in FILENAME.M
%
%   GPMODELGENES2MFILE(GP,'testbest','FILENAME') converts the 'best' model,
%   as evaluated on the test data, to a function in FILENAME.M
%
%   GPMODELGENES2MFILE(GP,ID,'FILENAME') converts the model with numeric
%   identifier ID in the population to a function in FILENAME.M
%
%   GPMODELGENES2MFILE(GP,ID,'FILENAME',USEALIAS) does the same but uses
%   variable aliases (if defined in gp.nodes.inputs.names) if USEALIAS is
%   TRUE.
%
%   GPMODELGENES2MFILE(GP,GPMODEL) operates on the GPMODEL struct
%   representing a multigene regression model, i.e. the struct returned by
%   the functions GPMODEL2STRUCT or GENES2GPMODEL.
%
%   Remarks:
%
%   This function is designed for use with multigene symbolic models
%   created with the REGRESSMULTI_FITFUN fitness function (or variant
%   thereof with fitness function filename beginning REGRESSMULTI). The
%   difference between this and GPMODEL2MFILE is that within the model file
%   generated the indivdiual outputs of the separate genes are exported as
%   the variable YGENES.
%
%   Note:
%
%   Requires Symbolic Math Toolbox.
%
%   Copyright (c) 2009-2015 Dominic Searson
%
%   GPTIPS 2
%
%   See also GPMODEL2MFILE, GPMODEL2SYM, GPMODEL2STRUCT, GPMODEL2FUNC

if nargin < 2
    disp('Usage is GPMODELGENES2MFILE(GP,IND) where IND is the population index of the desired individual');
    disp('or GPMODELGENES2MFILE(GP,''BEST'') to convert the best individual of run');
    disp('or GPMODELGENES2MFILE(GP,''VALBEST'') to convert the best validation individual of run.');
    return;
end

if nargin<3 || isempty(filename)
    filename = 'gpgenesmodel';
end

if nargin<4 || isempty(useAlias)
    useAlias = false;
end

if ~ischar(filename)
    error('The filename parameter must be a string.');
end

if gp.info.toolbox.symbolic
    
    %get model data
    disp('Simplifying model...');
    
    [~,genes_sym] = gppretty(gp,ID,false,true,false,useAlias);
    
    pat='x(\d+)';
    numGenes = numel(genes_sym);
    vectorModelStr = cell(numGenes,1);
    
    %loop through the individual genes and vectorise each separately (in
    %contrast with gpmodel2mfile which combines genes before simplication
    %and vectorisation)
    for i=1:numGenes
        
        %vectorise the whole multigene model and extract to string
        vectorModelStr{i}=['ygenes(:,' num2str(i) ')=' vectorize(genes_sym{i})];
        
        %replace x1,x2,x3 etc with x(:,1), x(:,2), x(:,3) etc.
        vectorModelStr{i} = regexprep(vectorModelStr{i},pat,'x(:,$1)');
    end
    
    if strcmp(filename(end-1:end),'.m')
        filename = filename(1:end-2);
    end
    
    %now open file and write m file header etc
    fid = fopen([filename '.m'],'w+');
    
    fprintf(fid,['function [ypred,ygenes]=' filename '(x)']);
    fprintf(fid,'\n');
    fprintf(fid,['%%'   upper(filename) ' This model file was automatically generated by the GPTIPS 2 function gpmodelgenes2mfile on ' datestr(now)]);
    fprintf(fid,'\n\n');
    
    %set up ygenes variable
    fprintf(fid, ['\nygenes = zeros(size(x,1),' num2str(numGenes)  ');\n']);
    
    %print line to evaluate each gene
    for i=1:numGenes
        fprintf(fid,[vectorModelStr{i} ';']);
        fprintf(fid,'\n');
    end
    
    %print line to get overall prediction ypred
    fprintf(fid, '\nypred = sum(ygenes,2);');
    fclose(fid);
    
    disp(['Model sucessfully written to ' filename '.m']);
else
    error('The Symbolic Math Toolbox is required to use this function.');
end